home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / sound / hc55516.c < prev    next >
C/C++ Source or Header  |  2000-04-04  |  5KB  |  194 lines

  1. #include "driver.h"
  2. #include <math.h>
  3.  
  4.  
  5. #define    INTEGRATOR_LEAK_TC        0.001
  6. #define    FILTER_DECAY_TC            0.004
  7. #define    FILTER_CHARGE_TC        0.004
  8. #define    FILTER_MIN                0.0416
  9. #define    FILTER_MAX                1.0954
  10. #define    SAMPLE_GAIN                10000.0
  11.  
  12.  
  13. struct hc55516_data
  14. {
  15.     INT8     channel;
  16.     UINT8    last_clock;
  17.     UINT8    databit;
  18.     UINT8    shiftreg;
  19.  
  20.     INT16    curr_value;
  21.     INT16    next_value;
  22.  
  23.     UINT32    update_count;
  24.  
  25.     double     filter;
  26.     double    integrator;
  27. };
  28.  
  29.  
  30. static struct hc55516_data hc55516[MAX_HC55516];
  31. static double charge, decay, leak;
  32.  
  33.  
  34. static void hc55516_update(int num, INT16 *buffer, int length);
  35.  
  36.  
  37.  
  38. int hc55516_sh_start(const struct MachineSound *msound)
  39. {
  40.     const struct hc55516_interface *intf = msound->sound_interface;
  41.     int i;
  42.  
  43.     /* compute the fixed charge, decay, and leak time constants */
  44.     charge = pow(exp(-1), 1.0 / (FILTER_CHARGE_TC * 16000.0));
  45.     decay = pow(exp(-1), 1.0 / (FILTER_DECAY_TC * 16000.0));
  46.     leak = pow(exp(-1), 1.0 / (INTEGRATOR_LEAK_TC * 16000.0));
  47.  
  48.     /* loop over HC55516 chips */
  49.     for (i = 0; i < intf->num; i++)
  50.     {
  51.         struct hc55516_data *chip = &hc55516[i];
  52.         char name[40];
  53.  
  54.         /* reset the channel */
  55.         memset(chip, 0, sizeof(*chip));
  56.  
  57.         /* create the stream */
  58.         sprintf(name, "HC55516 #%d", i);
  59.         chip->channel = stream_init(name, intf->volume[i] & 0xff, Machine->sample_rate, i, hc55516_update);
  60.  
  61.         /* bail on fail */
  62.         if (chip->channel == -1)
  63.             return 1;
  64.     }
  65.  
  66.     /* success */
  67.     return 0;
  68. }
  69.  
  70.  
  71. void hc55516_update(int num, INT16 *buffer, int length)
  72. {
  73.     struct hc55516_data *chip = &hc55516[num];
  74.     INT32 data, slope;
  75.     int i;
  76.  
  77.     /* zero-length? bail */
  78.     if (length == 0)
  79.         return;
  80.  
  81.     /* track how many samples we've updated without a clock */
  82.     chip->update_count += length;
  83.     if (chip->update_count > Machine->sample_rate / 32)
  84.     {
  85.         chip->update_count = Machine->sample_rate;
  86.         chip->next_value = 0;
  87.     }
  88.  
  89.     /* compute the interpolation slope */
  90.     data = chip->curr_value;
  91.     slope = ((INT32)chip->next_value - data) / length;
  92.     chip->curr_value = chip->next_value;
  93.  
  94.     /* reset the sample count */
  95.     for (i = 0; i < length; i++, data += slope)
  96.         *buffer++ = data;
  97. }
  98.  
  99.  
  100. void hc55516_clock_w(int num, int state)
  101. {
  102.     struct hc55516_data *chip = &hc55516[num];
  103.     int clock = state & 1, diffclock;
  104.  
  105.     /* update the clock */
  106.     diffclock = clock ^ chip->last_clock;
  107.     chip->last_clock = clock;
  108.  
  109.     /* speech clock changing (active on rising edge) */
  110.     if (diffclock && clock)
  111.     {
  112.         double integrator = chip->integrator, temp;
  113.  
  114.         /* clear the update count */
  115.         chip->update_count = 0;
  116.  
  117.         /* move the estimator up or down a step based on the bit */
  118.         if (chip->databit)
  119.         {
  120.             chip->shiftreg = ((chip->shiftreg << 1) | 1) & 7;
  121.             integrator += chip->filter;
  122.         }
  123.         else
  124.         {
  125.             chip->shiftreg = (chip->shiftreg << 1) & 7;
  126.             integrator -= chip->filter;
  127.         }
  128.  
  129.         /* simulate leakage */
  130.         integrator *= leak;
  131.  
  132.         /* if we got all 0's or all 1's in the last n bits, bump the step up */
  133.         if (chip->shiftreg == 0 || chip->shiftreg == 7)
  134.         {
  135.             chip->filter = FILTER_MAX - ((FILTER_MAX - chip->filter) * charge);
  136.             if (chip->filter > FILTER_MAX)
  137.                 chip->filter = FILTER_MAX;
  138.         }
  139.  
  140.         /* simulate decay */
  141.         else
  142.         {
  143.             chip->filter *= decay;
  144.             if (chip->filter < FILTER_MIN)
  145.                 chip->filter = FILTER_MIN;
  146.         }
  147.  
  148.         /* compute the sample as a 32-bit word */
  149.         temp = integrator * SAMPLE_GAIN;
  150.         chip->integrator = integrator;
  151.  
  152.         /* compress the sample range to fit better in a 16-bit word */
  153.         if (temp < 0)
  154.             chip->next_value = (int)(temp / (-temp * (1.0 / 32768.0) + 1.0));
  155.         else
  156.             chip->next_value = (int)(temp / (temp * (1.0 / 32768.0) + 1.0));
  157.  
  158.         /* update the output buffer before changing the registers */
  159.         stream_update(chip->channel, 0);
  160.     }
  161. }
  162.  
  163.  
  164. void hc55516_digit_w(int num, int data)
  165. {
  166.     hc55516[num].databit = data & 1;
  167. }
  168.  
  169.  
  170. void hc55516_clock_clear_w(int num, int data)
  171. {
  172.     hc55516_clock_w(num, 0);
  173. }
  174.  
  175.  
  176. void hc55516_clock_set_w(int num, int data)
  177. {
  178.     hc55516_clock_w(num, 1);
  179. }
  180.  
  181.  
  182. void hc55516_digit_clock_clear_w(int num, int data)
  183. {
  184.     hc55516[num].databit = data & 1;
  185.     hc55516_clock_w(num, 0);
  186. }
  187.  
  188.  
  189. WRITE_HANDLER( hc55516_0_digit_w )    { hc55516_digit_w(0,data); }
  190. WRITE_HANDLER( hc55516_0_clock_w )    { hc55516_clock_w(0,data); }
  191. WRITE_HANDLER( hc55516_0_clock_clear_w )    { hc55516_clock_clear_w(0,data); }
  192. WRITE_HANDLER( hc55516_0_clock_set_w )        { hc55516_clock_set_w(0,data); }
  193. WRITE_HANDLER( hc55516_0_digit_clock_clear_w )    { hc55516_digit_clock_clear_w(0,data); }
  194.